﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace V32Assembler
{
    class Program
    {
        private static bool Preprocess = false;
        private static bool Addresses = false;

        private static void ShowUsage()
        {
            Console.Error.Write(
                "Usage: V32Assembler [options] asm [asm asm ... ]\n" +
                "  options:\n" +
                "    -p/--preprocess: output preprocessed files as .pasm\n" +
                "    -a/--addresses: output preprocessed files with labels and command\n" +
                "                    addresses as .asmaddr\n"
            );
        }
        static int Main(string[] args)
        {
            try
            {
                //args = new[] { "-pa", "forth.asm" };
                args = CmdLineOptions.Get(args, new[] {
                    new Tuple<char, string, Action>('p', "preprocess", () => Preprocess = true),
                    new Tuple<char, string, Action>('a', "addresses", () => Addresses = true)
                }).ToArray();
            }
            catch (Exception e)
            {
                Console.Error.WriteLine(e.Message);
                ShowUsage();
                return -1;
            }

            bool wasError = args.Length == 0;
            if (wasError)
                ShowUsage();
            foreach (string arg in args)
            {
                if (!System.IO.File.Exists(arg)) { Console.Error.WriteLine("Could not find file '{0}'.", arg); continue; }

                string[] input;
                try { input = System.IO.File.ReadAllLines(arg); }
                catch (Exception) { Console.Error.WriteLine("Could not read file '{0}'.", arg); continue; }

                Output[] outputs = new Output[0];
                try { outputs = Assembler.Assemble(input, Preprocess, Addresses); }
                catch (Exception) { }

                if (Assembler.Errors.Count > 0)
                {
                    wasError = true;
                    Console.Error.WriteLine("File '{0}' had {1} error{2}:",
                        arg,
                        Assembler.Errors.Count,
                        Assembler.Errors.Count == 1 ? "" : "s");
                    foreach (Error e in Assembler.Errors)
                        Console.Error.WriteLine("    Error on line {0}: {1}", e.LineNumber + 1, e.Message);
                    continue;
                }

                foreach (Output output in outputs)
                {
                    try { output.Write(arg); }
                    catch (Exception) { Console.Error.WriteLine(output.GetErrorMessage(arg)); continue; }
                    Console.WriteLine(output.GetSuccessMessage(arg));
                }
            }

            return wasError ? -1 : 0; // lol I need Forth bools here (false=0, true=-1)
        }
    }
}
